package com.example.matchingengine.service.facade;

import com.example.matchingengine.model.Order;
import com.example.matchingengine.service.MatchingEngineService;
import com.example.matchingengine.service.model.OrderBook;
import com.example.matchingengine.service.model.OrderBookSnapshot;
import com.example.matchingengine.service.strategy.PrototypeStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 撮合引擎门面类
 * 使用门面模式简化客户端对撮合引擎复杂子系统的访问
 * 提供统一的、简化的接口来处理订单操作
 */
@Slf4j
@Component
public class MatchingEngineFacade {
    
    @Autowired
    private MatchingEngineService matchingEngineService;
    
    /**
     * 提交限价买单
     * @param symbol 交易对
     * @param userId 用户ID
     * @param price 价格
     * @param quantity 数量
     * @return 订单ID
     */
    public String submitLimitBuyOrder(String symbol, String userId, BigDecimal price, BigDecimal quantity) {
        return submitLimitBuyOrder(symbol, userId, price, quantity, Order.TimeInForce.GTC);
    }
    
    /**
     * 提交限价买单（指定时效）
     * @param symbol 交易对
     * @param userId 用户ID
     * @param price 价格
     * @param quantity 数量
     * @param timeInForce 时效类型
     * @return 订单ID
     */
    public String submitLimitBuyOrder(String symbol, String userId, BigDecimal price, 
                                     BigDecimal quantity, Order.TimeInForce timeInForce) {
        try {
            log.info("提交限价买单: symbol={}, userId={}, price={}, quantity={}, timeInForce={}", 
                    symbol, userId, price, quantity, timeInForce);
            
            Order order = createLimitOrder(symbol, userId, Order.OrderSide.BUY, price, quantity, timeInForce);
            matchingEngineService.processOrder(order);
            
            log.info("限价买单提交成功: orderId={}", order.getId());
            return order.getId();
        } catch (Exception e) {
            log.error("提交限价买单失败: {}", e.getMessage(), e);
            throw new RuntimeException("提交限价买单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 提交限价卖单
     * @param symbol 交易对
     * @param userId 用户ID
     * @param price 价格
     * @param quantity 数量
     * @return 订单ID
     */
    public String submitLimitSellOrder(String symbol, String userId, BigDecimal price, BigDecimal quantity) {
        return submitLimitSellOrder(symbol, userId, price, quantity, Order.TimeInForce.GTC);
    }
    
    /**
     * 提交限价卖单（指定时效）
     * @param symbol 交易对
     * @param userId 用户ID
     * @param price 价格
     * @param quantity 数量
     * @param timeInForce 时效类型
     * @return 订单ID
     */
    public String submitLimitSellOrder(String symbol, String userId, BigDecimal price, 
                                      BigDecimal quantity, Order.TimeInForce timeInForce) {
        try {
            log.info("提交限价卖单: symbol={}, userId={}, price={}, quantity={}, timeInForce={}", 
                    symbol, userId, price, quantity, timeInForce);
            
            Order order = createLimitOrder(symbol, userId, Order.OrderSide.SELL, price, quantity, timeInForce);
            matchingEngineService.processOrder(order);
            
            log.info("限价卖单提交成功: orderId={}", order.getId());
            return order.getId();
        } catch (Exception e) {
            log.error("提交限价卖单失败: {}", e.getMessage(), e);
            throw new RuntimeException("提交限价卖单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 提交市价买单
     * @param symbol 交易对
     * @param userId 用户ID
     * @param quantity 数量
     * @return 订单ID
     */
    public String submitMarketBuyOrder(String symbol, String userId, BigDecimal quantity) {
        try {
            log.info("提交市价买单: symbol={}, userId={}, quantity={}", symbol, userId, quantity);
            
            Order order = createMarketOrder(symbol, userId, Order.OrderSide.BUY, quantity);
            matchingEngineService.processOrder(order);
            
            log.info("市价买单提交成功: orderId={}", order.getId());
            return order.getId();
        } catch (Exception e) {
            log.error("提交市价买单失败: {}", e.getMessage(), e);
            throw new RuntimeException("提交市价买单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 提交市价卖单
     * @param symbol 交易对
     * @param userId 用户ID
     * @param quantity 数量
     * @return 订单ID
     */
    public String submitMarketSellOrder(String symbol, String userId, BigDecimal quantity) {
        try {
            log.info("提交市价卖单: symbol={}, userId={}, quantity={}", symbol, userId, quantity);
            
            Order order = createMarketOrder(symbol, userId, Order.OrderSide.SELL, quantity);
            matchingEngineService.processOrder(order);
            
            log.info("市价卖单提交成功: orderId={}", order.getId());
            return order.getId();
        } catch (Exception e) {
            log.error("提交市价卖单失败: {}", e.getMessage(), e);
            throw new RuntimeException("提交市价卖单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 取消订单
     * @param symbol 交易对
     * @param orderId 订单ID
     * @return 是否取消成功
     */
    public boolean cancelOrder(String symbol, String orderId) {
        try {
            log.info("取消订单: symbol={}, orderId={}", symbol, orderId);
            
            matchingEngineService.cancelOrder(orderId, symbol);
            boolean result = true; // 假设取消成功，实际应该检查订单状态
            
            if (result) {
                log.info("订单取消成功: orderId={}", orderId);
            } else {
                log.warn("订单取消失败: orderId={}", orderId);
            }
            
            return result;
        } catch (Exception e) {
            log.error("取消订单失败: orderId={}, 错误: {}", orderId, e.getMessage(), e);
            throw new RuntimeException("取消订单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 查询订单状态
     * @param symbol 交易对
     * @param orderId 订单ID
     * @return 订单信息
     */
    public Order queryOrder(String symbol, String orderId) {
        try {
            log.debug("查询订单: symbol={}, orderId={}", symbol, orderId);
            
            // 通过订单簿查询订单
            OrderBook orderBook = getOrderBook(symbol);
            Order order = orderBook != null ? orderBook.getOrderMap().get(orderId) : null;
            
            if (order != null) {
                log.debug("订单查询成功: orderId={}, status={}", orderId, order.getStatus());
            } else {
                log.warn("订单不存在: orderId={}", orderId);
            }
            
            return order;
        } catch (Exception e) {
            log.error("查询订单失败: orderId={}, 错误: {}", orderId, e.getMessage(), e);
            throw new RuntimeException("查询订单失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取订单簿快照
     * @param symbol 交易对
     * @return 订单簿快照
     */
    public OrderBookSnapshot getOrderBookSnapshot(String symbol) {
        try {
            log.debug("获取订单簿快照: symbol={}", symbol);
            
            // 通过订单簿获取快照
            OrderBook orderBook = getOrderBook(symbol);
            OrderBookSnapshot snapshot = orderBook != null ? createOrderBookSnapshot(orderBook) : null;
            
            log.debug("订单簿快照获取成功: symbol={}", symbol);
            
            return snapshot;
        } catch (Exception e) {
            log.error("获取订单簿快照失败: symbol={}, 错误: {}", symbol, e.getMessage(), e);
            throw new RuntimeException("获取订单簿快照失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 创建订单簿快照
     */
    private OrderBookSnapshot createOrderBookSnapshot(OrderBook orderBook) {
        OrderBookSnapshot snapshot = new OrderBookSnapshot();
        snapshot.setSymbol(orderBook.getSymbol());
        // 这里可以根据需要添加更多快照数据
        return snapshot;
    }
    
    /**
     * 获取系统统计信息
     * @return 统计信息
     */
    public Map<String, Object> getSystemStats() {
        try {
            log.debug("获取系统统计信息");
            
            Map<String, Object> stats = Map.of(
                "prototypeStrategyCount", PrototypeStrategyFactory.getPrototypeCount(),
                "engineServiceClass", matchingEngineService.getClass().getSimpleName()
            );
            
            log.debug("系统统计信息获取成功: {}", stats);
            return stats;
        } catch (Exception e) {
            log.error("获取系统统计信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取系统统计信息失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 创建限价订单
     */
    private Order createLimitOrder(String symbol, String userId, Order.OrderSide side, 
                                  BigDecimal price, BigDecimal quantity, Order.TimeInForce timeInForce) {
        return Order.builder()
                .id(generateOrderId())
                .symbol(symbol)
                .userId(userId)
                .side(side)
                .type(Order.OrderType.LIMIT)
                .timeInForce(timeInForce)
                .price(price)
                .quantity(quantity)
                .filledQuantity(BigDecimal.ZERO)
                .status(Order.OrderStatus.NEW)
                .build();
    }
    
    /**
     * 创建市价订单
     */
    private Order createMarketOrder(String symbol, String userId, Order.OrderSide side, BigDecimal quantity) {
        return Order.builder()
                .id(generateOrderId())
                .symbol(symbol)
                .userId(userId)
                .side(side)
                .type(Order.OrderType.MARKET)
                .timeInForce(Order.TimeInForce.IOC) // 市价单默认IOC
                .price(BigDecimal.ZERO) // 市价单无价格
                .quantity(quantity)
                .filledQuantity(BigDecimal.ZERO)
                .status(Order.OrderStatus.NEW)
                .build();
    }
    
    /**
     * 生成订单ID
     */
    private String generateOrderId() {
        return "ORD_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
    }
    
    /**
     * 获取订单簿（通过反射访问私有字段）
     */
    private OrderBook getOrderBook(String symbol) {
        try {
            java.lang.reflect.Field field = matchingEngineService.getClass().getDeclaredField("orderBooks");
            field.setAccessible(true);
            @SuppressWarnings("unchecked")
            Map<String, OrderBook> orderBooks = (Map<String, OrderBook>) field.get(matchingEngineService);
            return orderBooks.get(symbol);
        } catch (Exception e) {
            log.error("获取订单簿失败: symbol={}, 错误: {}", symbol, e.getMessage(), e);
            return null;
        }
    }
}